package com.daniel.create.singleton;

import java.io.Serializable;
import java.util.concurrent.*;

/**
 * @Description 枚举实现，这是单例模式的最佳实践，它实现简单，并且在面对复杂的序列化或者反射攻击的时候，能够防止实例化多次。
 * @Author GanShaoXi
 * @ClassName SingletonPattern_1
 * @Return com.daniel.create.singleton
 * @Since 1.0.0
 * @Created on 2023/5/16 19:43
 */
public class SingletonPattern_6 implements Serializable {

    private String flag;

    private SingletonPattern_6(String flag) {
        this.flag = flag;
    }

    /**
     * @Description Java虚拟机会保证枚举类型不能被反射并且构造函数只被执行一次。在这里我们只需要在其中增加一个内部枚举类型来存储和创建它的唯一实例即可，
     * 这和前面的静态内部类的实现有点相似，但是枚举实现可以很好地解决反射和反序列化会破坏单例模式的问题，提供了一种更加安全和可靠的单例模式实现机制。
     * @Author GanShaoXi
     * @ClassName SingletonPattern_6
     * @Return com.daniel.create.singleton
     * @Since 1.0.0
     * @Created on 2023/5/16 23:13
     */
    public static enum SingletonEnum {
        /*SingletonPattern_6的实例*/
        SINGLETON;
        private SingletonPattern_6 instance = null;

        private SingletonEnum() {
            instance = new SingletonPattern_6(Thread.currentThread().getName());
        }

        public SingletonPattern_6 getInstance() {
            return instance;
        }
    }


    /**
     * 测试多线程下实例创建
     *
     * @param args
     */
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, 5, 5, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "singleton_task_pool" + r.hashCode());
            }
        });
        // 执行16次
        for (int i = 1; i <= 5; i++) {
            threadPoolExecutor.execute(new MyRunnable(i));
        }
        // threadPoolExecutor.shutdown();
    }
}

class MyRunnable implements Runnable {
    private int i;

    public MyRunnable(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        try {
            long l = (long) (Math.random()*4*1000+1);
            System.out.println(l);
            Thread.sleep(l);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SingletonPattern_6 singletonPattern6 = SingletonPattern_6.SingletonEnum.SINGLETON.getInstance();
        System.out.println(Thread.currentThread().getName() + "  执行了任务" + i + "-> The instance created by the current thread is:" + singletonPattern6);
    }
}